package sdk.org.apache.shiro.G2_使用.C05_认证_3重试次数;

import java.net.URL;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;

import com.titan.core.utils.io.ConsoleUtils;

import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Ehcache;
import net.sf.ehcache.Element;
import sdk.org.apache.shiro.utils.ShiroUtils;


public class RetryLimitHashedCredentialsMatcher extends HashedCredentialsMatcher {
    private Ehcache passwordRetryCache;

    public RetryLimitHashedCredentialsMatcher() {
        URL url = CacheManager.class.getClassLoader().getResource("sdk/org/apache/shiro/G2_使用/C05_认证_3重试次数/password-ehcache.xml");
        CacheManager cacheManager = CacheManager.create(url);
        passwordRetryCache = cacheManager.getCache("passwordRetryCache");
    }

    @Override
    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
        String username = ShiroUtils.getUsername(token);
        //retry count + 1
        Element element = passwordRetryCache.get(username);
        if(element == null) {
            element = new Element(username , new AtomicInteger(0));
            passwordRetryCache.put(element);
        }
        AtomicInteger retryCount = (AtomicInteger)element.getObjectValue();
        if(retryCount.incrementAndGet() > 5) {
            //if retry count > 5 throw
            throw new ExcessiveAttemptsException("用户登录重复次数："+retryCount.get());
        }
        
        boolean matches = super.doCredentialsMatch(token, info);
        ConsoleUtils.method(RetryLimitHashedCredentialsMatcher.class, "doCredentialsMatch", "username", username, "matches", matches, "retryCount", retryCount.get());
        if(matches) {
            //clear retry count
            passwordRetryCache.remove(username);
        } else {
            element = new Element(username , retryCount);
            passwordRetryCache.put(element);
        }
        return matches;
    }
}
